package com.woniu.cq.mallorder.common;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Daniel
 * @version 1.0.0
 * @ClassName RedisLock
 * @Description TODO
 * @createTime 2020年09月29日 22:42:00
 */
@Component
public class RedisLock {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final Integer TIME_OUT = 5;
    /**
     * @description: 存当前枷锁者value
     * @param: null
     * @return:
     */
    private ThreadLocal<String> tl = new ThreadLocal<>();
    /**
     * @description: 存重入次数
     * @param: null
     * @return:
     */
    private ThreadLocal<Integer> count = new ThreadLocal<>();
    /** 
     * @description: 加锁 
     * @param: key 
     * @return: boolean 
     */
    public boolean lock(String key) {
        String value = UUID.randomUUID().toString();
        long start = System.currentTimeMillis();
        while (true) {
            if (count.get() != null) {
                count.set(count.get() + 1);
                return true;
            }
            Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(key, value, 30, TimeUnit.SECONDS);
            if (b) {
                tl.set(value);
                count.set(0);
                return true;
            }
            if (System.currentTimeMillis() - start >= TIME_OUT * 5) {
                return false;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /** 
     * @description: 解锁 
     * @param: key 
     * @return: void 
     */
    public void unlock(String key) {
        if (StringUtils.isNotEmpty(key)) {
            String value = stringRedisTemplate.opsForValue().get(key);
            if (StringUtils.isNotEmpty(value) && value.equals(tl.get())) {
                if (count.get() != null && count.get() > 0) {
                    count.set(count.get() - 1);
                } else {
                    tl.set(null);
                    stringRedisTemplate.delete(key);
                }
            }
        }
    }
}
